/*
 * IteradorLista.h
 *
 *  Created on: Mar 24, 2011
 *      Author: Francisco
 */

#ifndef ITERADOR_LISTA_H
#define ITERADOR_LISTA_H

#include "Nodo.h"
#include "ElementoInexistenteException.h"

template<class T> class Lista;

template<class T> class IteradorLista {

private:

	Lista<T>* lista;

	Nodo<T>* actual;

public:

	IteradorLista(Lista<T>* lista) {
		this->setLista(lista);
		this->setActual(this->getLista()->getPrimero());
	}

	virtual ~IteradorLista() {
	}

	bool tieneSiguiente() {
		return this->getActual() != NULL;
	}

	T siguiente() {
		T dato = this->get();
		this->setActual(this->getActual()->getSiguiente());
		return dato;
	}

	T get() {
		if (this->getActual() == NULL) {
			throw ElementoInexistenteException("No se puede obtener");
		}
		return this->getActual()->getDato();
	}

	void set(T elemento) {
		if (this->getActual() == NULL) {
			throw ElementoInexistenteException("No se puede cambiar");
		}
		//return this->getActual()->setDato(elemento);
		this->getActual()->setDato(elemento);
	}

	T remover() {
		T dato = this->get();

		Nodo<T>* anterior = this->getActual()->getAnterior();
		Nodo<T>* siguiente = this->getActual()->getSiguiente();

		if (anterior != NULL) {
			anterior->setSiguiente(siguiente);
		} else {
			this->getLista()->setPrimero(siguiente);
		}

		if (siguiente != NULL) {
			siguiente->setAnterior(anterior);
		} else {
			this->getLista()->setUltimo(anterior);
		}

		delete this->getActual();
		this->setActual(siguiente);
		return dato;
	}

	void insertar(T dato) {
		Nodo<T>* actual = this->getActual();
		Nodo<T>* anterior = NULL;
		Nodo<T>* siguiente = actual;
		if (actual != NULL) {
			anterior = actual->getAnterior();
		} else {
			anterior = this->getLista()->getUltimo();
		}
		this->insertar(dato, anterior, siguiente);
	}

	void primero() {
		//this->setProgresivo(true);
		this->setActual(this->getLista()->getPrimero());
	}

	void ultimo() {
		//this->setProgresivo(false);
		this->setActual(this->getLista()->getUltimo());
	}

private:

	void setActual(Nodo<T>* nodo) {
		this->actual = nodo;
	}

	Nodo<T>* getActual() {
		return this->actual;
	}

	Lista<T>* getLista() {
		return this->lista;
	}

	void setLista(Lista<T>* lista) {
		this->lista = lista;
	}

	void insertar(T dato, Nodo<T>* anterior, Nodo<T>* siguiente) {
		Nodo<T>* nuevo = new Nodo<T> (dato);
		nuevo->setAnterior(anterior);
		nuevo->setSiguiente(siguiente);

		if (anterior != NULL) {
			anterior->setSiguiente(nuevo);
		} else {
			this->getLista()->setPrimero(nuevo);
		}

		if (siguiente != NULL) {
			siguiente->setAnterior(nuevo);
		} else {
			this->getLista()->setUltimo(nuevo);
		}

		this->setActual(nuevo);
	}
};

#endif
